// -*-c#-*-
// License: New BSD License : http://www.opensource.org/licenses/bsd-license.php
//
// Copyright (c) 2008, Brothers In Arms/Burl Nyswonger
//
// See: BiaVote.uc for full License
// 
//@L

`include( BiaVote/Classes/BiaStdInc.uci) 
`include( BiaVote/Classes/BiaVote.uci  ) 

`if(`isdefined(UNIT_TEST))

class BiaVoteUnitTest extends Info
    Config( BiaVoteUnitTest );

// ----------------------------------------------------------------------------
    

// ----------------------------------------------------------------------------

struct s_SimVote
{
    var int T, P, W, S;  //TestCase#, Player#, Waits-to-vote, Sleeps-after-vote
    var biaVType V;      //Vote Type   
    var bool I;          //Is an Idler?
    var string C;        //Choice (will be looked up in biaVL/etc...)
    var float LastVote;  //time of last vote
    var bool Voted;      //ignore this if true
    structdefaultproperties
    {
        T=0  
        P=0
        I=false
        W=3
        S=10
        C="DM"
    }
};

var config array<s_SimVote> SimVote;
var array<s_SimVote>        aRound;
var array<int>              aPlayers;


var BiaVote BV;    // The instance of BiaVote
var int Citizens;  // phony number of voting-players
var bool bTesting; // when Unit Test is enabled

var int nRound;    // Which round of voting we're testing.
var int tDelta;    // how long since the round began

// ---------------------------------------------------------------------------
// interface to BiaVote

function StartTests( BiaVote Master )
{
    BV = Master;

    aPlayers.Length = 0;    
    aRound.Length = 0;
    nRound = -1;
    SetTimer(1.0, true);
    GotoState('NextTest');
}

state NextTest
{
    function BeginState( name PrevState )
    {
        nRound = nRound + 1;
        GatherTestData();
    }
    function Timer()
    {
        if( BV.bVoteReady )
        {
            GotoState('Voting');
        }
    }
}

state Voting
{
    function BeginState( name PrevState )
    {
        `BiaDbg("Beginning test round...");
        tDelta = 0;
    }
    function Timer()
    {
        local bool bVoted;
        local int i;

        tDelta += 1;
        bVoted = false;
        
        for(i = 0; i < aRound.Length; i++)
        {
            if( aRound[i].Voted )
            {
                continue;
            }
            aRound[i].Voted = true;
            if( aRound[i].I )
            {
                `BiaDbg("ut_Player_" $ aRound[i].P $ " is an Idler");
                return;
            }
            SubmitVote(i, aRound[i].P);
            bVoted = true;
            break;
        }
        if( !bVoted )
        {
            `BiaDbg("No more sim data - ending sim round");
            GotoState('VoteOver');
        }
    }
}

state VoteOver
{
    function BeginState( name PrevState )
    {
        tDelta = 0;
    }
    function Timer()
    {
        `BiaDbg("UNIT_TEST: Tick...");
        
        tDelta += 1;
        if( tDelta > BV.nVoteTimeLimit + 2 )
        {
            KillPlayers();
        }
        if( tDelta > BV.nVoteTimeLimit + 5 )
        {
            `BiaDbg("Switching to next vote round (if any)");
            GotoState('NextTest');
        }
    }
}

state EndTesting
{
    function BeginState( name PrevState )
    {
        bTesting = false;
        ClearTimer();
        `BiaDbg("Unit Test Complete -- review the log");
    }
}

function Timer()
{
    `BiaDbg("UNIT-TEST: Tick.");
}


// ---------------------------------------------------------------------------
// Private/Internal

private function KillPlayers()
{
    local int i;
    
    for(i = 0; i < BV.aPlayers.Length; i++)
    {
        if(BV.aPlayers[i].bUnitTest)
        {
            BV.aPlayers[i].bUnitTest = false;
            BV.aPlayers[i].Id = 0;
            BV.aPlayers[i].bIsBot = true;
            BV.aPlayers[i].PlayerName = "";
            BV.aPlayers[i].Votes.Length = 0;
        }
    }
}

private function SubmitVote( int idx, int pnum )
{
    local int i, j, pIdx;
    local bool bVoted;
    local string pn;
    
    pn = "ut_Player_" $ pnum;

    `BiaDbg("Attempting to submit vote, vType: " $ aRound[idx].V);

    pIdx = -1;
    for(j = 0; j < BV.aPlayers.Length; j++)
    {
        if( BV.aPlayers[j].PlayerName ~= pn )
        {
            pIdx = j;
            break;
        }
    }
    if( pIdx > -1 ) {
        for(i = 0; i < BV.biaVL.Length; i++)
        {
            if(BV.biaVL[i].vType == aRound[idx].V &&
               BV.biaVL[i].Title ~= aRound[idx].C )
            {
                BV.Player_SubmitVote(pIdx, BV.biaVL[i].Id);
                bVoted = true;
                break;
            }
        }
    }
    if( bVoted )
    {
        `BiaDbg("Submitted vote");
    }
    else
    {
        `BiaDbg("Failed to submit vote!");
    }
}

private function GatherTestData()
{
    local int i, idx;
    local bool bAny;
    
    Citizens = 0;    
    aRound.Length = 0;
    
    aPlayers.Length = 0;
    bAny = false;
    
    for(i=0; i < SimVote.Length; i++)
    {
        if( SimVote[i].T == nRound )
        {
            idx = aRound.Length;
            aRound.AddItem( SimVote[i] );
            aRound[idx].Voted = false;
            if( aPlayers.Find(aRound[idx].P) < 0 )
            {
                aPlayers.AddItem(aRound[idx].P);
                Citizens += 1;
                BV.ut_StartPlayer( "ut_Player_" $ aRound[idx].P );
            }
            bAny = true;
        }
    }
    if( !bAny )
    {
        `BiaDbg("Didn't find any test cases for round#" $ nRound);
        GotoState('EndTest');
    }
    
}



// --------------------------------------------------------------------------

`else

class BiaVoteUnitTest extends Object;

`endif

defaultproperties
{
}
